#include "Dwarf.Unmanaged.Mpi.h"

using namespace std;

// The settings for this dwarf.
static Settings* settings;

// Get settings from the command line.
static int getSettings(int argc, char** argv, Solver *solver) 
{
    int error = 0;
    if (solver->isRootThread) 
    {
        settings = new Settings();
        //Parse all arguments for dwarf.
        if (settings->init(argc,argv,solver)) 
        {            
            delete settings;
            error = 1;
        }
    }
    //Distribute error if that occurred while parsing.
    MPI_Bcast(&error, 1, MPI_INT, NUMBER_ROOT_PROCESS, MPI_COMM_WORLD);
    if (error == 1 ) return -1;
    //Distribute the length of matrix.
    MPI_Bcast(&solver->length, 1, MPI_INT, 0 , MPI_COMM_WORLD);
    if(!solver->isRootThread)
    {
        solver->init();
    }

    /*Set up of balance*/
    if(solver->commRank  == (solver->commSize - 1) )
    {
        solver->lengthForProc = solver->length - (solver->length / solver->commSize) * solver->commRank;
    } 
    else
    {
        solver->lengthForProc = solver->length / solver->commSize;
    }

    return 0;
}

// Point of the program start.
void main(int argc, char** argv)
{
    MPI_Init(&argc, &argv);

    Solver* solver = new Solver();
    // Get settings from the command line.
    if (getSettings(argc, argv, solver))
    {
        delete solver;
        exit(-1);
    }

    MPI_Barrier(MPI_COMM_WORLD);

    if (solver->isRootThread) 
    {
        printf("Start computing...\r\n");
        settings->start();                      // Start new time count.
    }

    solver->solve();                            // Solve the current problem.

    MPI_Barrier(MPI_COMM_WORLD);

    if (solver->isRootThread) 
    {
        settings->finish(solver);               // Stop the time count and write results. 
        delete settings;
    }

    delete solver;

    MPI_Finalize();
}
